<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>家谱可视化系统</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Microsoft YaHei', sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #f5f7fa 0%, #e4efe9 100%);
            color: #333;
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
            overflow: hidden;
        }
        
        header {
            background: linear-gradient(90deg, #2c3e50 0%, #4a6572 100%);
            color: white;
            padding: 20px;
            text-align: center;
        }
        
        h1 {
            font-size: 2.2rem;
            margin-bottom: 10px;
        }
        
        .subtitle {
            font-size: 1rem;
            opacity: 0.8;
        }
        
        .main-content {
            display: flex;
            min-height: 600px;
        }
        
        .sidebar {
            width: 300px;
            background: #f8f9fa;
            padding: 20px;
            border-right: 1px solid #eaeaea;
        }
        
        .control-panel {
            margin-bottom: 30px;
        }
        
        h2 {
            font-size: 1.2rem;
            margin-bottom: 15px;
            color: #2c3e50;
            border-bottom: 2px solid #4a6572;
            padding-bottom: 5px;
        }
        
        .upload-area {
            border: 2px dashed #ccc;
            border-radius: 8px;
            padding: 20px;
            text-align: center;
            margin-bottom: 20px;
            cursor: pointer;
            transition: all 0.3s;
        }
        
        .upload-area:hover {
            border-color: #4a6572;
            background: #f0f4f8;
        }
        
        .upload-icon {
            font-size: 2.5rem;
            color: #4a6572;
            margin-bottom: 10px;
        }
        
        .filters {
            margin-top: 20px;
        }
        
        input,
        select {
            width: 100%;
            padding: 10px;
            margin-bottom: 15px;
            border: 1px solid #ddd;
            border-radius: 5px;
        }
        
        button {
            background: #4a6572;
            color: white;
            border: none;
            padding: 12px 20px;
            border-radius: 5px;
            cursor: pointer;
            width: 100%;
            font-size: 1rem;
            transition: background 0.3s;
        }
        
        button:hover {
            background: #2c3e50;
        }
        
        .visualization-area {
            flex: 1;
            padding: 20px;
            position: relative;
            overflow: hidden;
            background: #fff;
        }
        
        .person-card {
            position: absolute;
            width: 180px;
            background: white;
            border-radius: 10px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
            padding: 15px;
            text-align: center;
            transition: all 0.3s;
            z-index: 1;
        }
        
        .person-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
            z-index: 2;
        }
        
        .person-img {
            width: 80px;
            height: 80px;
            border-radius: 50%;
            object-fit: cover;
            margin: 0 auto 10px;
            border: 3px solid #e4efe9;
        }
        
        .person-name {
            font-weight: bold;
            margin-bottom: 5px;
            color: #2c3e50;
        }
        
        .person-details {
            font-size: 0.8rem;
            color: #666;
        }
        
        .connector {
            position: absolute;
            background: #a0aec0;
            z-index: 0;
        }
        
        .controls {
            position: absolute;
            bottom: 20px;
            right: 20px;
            display: flex;
            gap: 10px;
        }
        
        .control-btn {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.2rem;
        }
        
        footer {
            text-align: center;
            padding: 15px;
            background: #f8f9fa;
            color: #666;
            font-size: 0.9rem;
        }
        
        .highlight {
            border: 2px solid #4a6572;
        }
        
        .male {
            border-left: 4px solid #3498db;
        }
        
        .female {
            border-left: 4px solid #e91e63;
        }
    </style>
</head>

<body>
    <div class="container">
        <header>
            <h1>家谱可视化系统</h1>
            <p class="subtitle">基于Web的牒记式家谱展示平台</p>
        </header>

        <div class="main-content">
            <div class="sidebar">
                <div class="control-panel">
                    <h2>数据导入</h2>
                    <div class="upload-area" id="uploadArea">
                        <div class="upload-icon">📁</div>
                        <p>点击或拖拽CSV文件到此处</p>
                        <input type="file" id="csvFile" accept=".csv" style="display: none;">
                    </div>

                    <div class="filters">
                        <h2>筛选与搜索</h2>
                        <input type="text" id="searchInput" placeholder="输入姓名搜索...">
                        <select id="generationFilter">
                            <option value="">所有世代</option>
                            <option value="1">第一代</option>
                            <option value="2">第二代</option>
                            <option value="3">第三代</option>
                            <option value="4">第四代</option>
                        </select>
                        <button id="resetView">重置视图</button>
                    </div>
                </div>

                <div class="info-panel">
                    <h2>使用说明</h2>
                    <p>1. 上传CSV格式的家谱数据文件</p>
                    <p>2. 系统将自动生成家谱可视化图</p>
                    <p>3. 点击人物卡片查看详细信息</p>
                    <p>4. 使用筛选功能查找特定成员</p>
                </div>
            </div>

            <div class="visualization-area" id="visualizationArea">
                <!-- 家谱可视化将在这里生成 -->
                <div class="connector" id="connector"></div>

                <div class="controls">
                    <button class="control-btn" id="zoomIn">+</button>
                    <button class="control-btn" id="zoomOut">-</button>
                    <button class="control-btn" id="resetZoom">↺</button>
                </div>
            </div>
        </div>

        <footer>
            <p>© 2023 家谱可视化系统 | 使用现代Web技术构建</p>
        </footer>
    </div>

    <script>
        // 示例数据（实际应用中将从CSV文件加载）
        const sampleData = [{
            id: 1,
            name: "张大明",
            gender: "男",
            father: null,
            mother: null,
            birthdate: "1950-01-15",
            birthplace: "北京"
        }, {
            id: 2,
            name: "李小红",
            gender: "女",
            father: null,
            mother: null,
            birthdate: "1952-05-20",
            birthplace: "上海"
        }, {
            id: 3,
            name: "张中华",
            gender: "男",
            father: 1,
            mother: 2,
            birthdate: "1975-08-12",
            birthplace: "北京"
        }, {
            id: 4,
            name: "王丽娟",
            gender: "女",
            father: null,
            mother: null,
            birthdate: "1978-03-25",
            birthplace: "广州"
        }, {
            id: 5,
            name: "张小强",
            gender: "男",
            father: 3,
            mother: 4,
            birthdate: "2000-11-05",
            birthplace: "深圳"
        }, {
            id: 6,
            name: "张小花",
            gender: "女",
            father: 3,
            mother: 4,
            birthdate: "2003-07-18",
            birthplace: "深圳"
        }];

        // 初始化函数
        function init() {
            // 绑定事件监听器
            document.getElementById('uploadArea').addEventListener('click', () => {
                document.getElementById('csvFile').click();
            });

            document.getElementById('csvFile').addEventListener('change', handleFileUpload);
            document.getElementById('searchInput').addEventListener('input', filterTree);
            document.getElementById('generationFilter').addEventListener('change', filterTree);
            document.getElementById('resetView').addEventListener('click', resetView);
            document.getElementById('zoomIn').addEventListener('click', zoomIn);
            document.getElementById('zoomOut').addEventListener('click', zoomOut);
            document.getElementById('resetZoom').addEventListener('click', resetZoom);

            // 使用示例数据生成家谱
            generateFamilyTree(sampleData);
        }

        // 处理文件上传
        function handleFileUpload(event) {
            const file = event.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = function(e) {
                    const csvData = parseCSV(e.target.result);
                    generateFamilyTree(csvData);
                };
                reader.readAsText(file);
            }
        }

        // 解析CSV文件（简化实现）
        function parseCSV(csvText) {
            // 实际应用中需要更完整的CSV解析逻辑
            const lines = csvText.split('\n');
            const headers = lines[0].split(',');

            const data = [];
            for (let i = 1; i < lines.length; i++) {
                if (lines[i].trim() === '') continue;

                const obj = {};
                const currentline = lines[i].split(',');

                for (let j = 0; j < headers.length; j++) {
                    obj[headers[j].trim()] = currentline[j] ? currentline[j].trim() : '';
                }

                data.push(obj);
            }

            return data;
        }

        // 生成家谱树
        function generateFamilyTree(data) {
            const visualizationArea = document.getElementById('visualizationArea');
            visualizationArea.innerHTML = '<div class="connector" id="connector"></div>';

            // 添加控制按钮
            const controls = document.createElement('div');
            controls.className = 'controls';
            controls.innerHTML = `
                <button class="control-btn" id="zoomIn">+</button>
                <button class="control-btn" id="zoomOut">-</button>
                <button class="control-btn" id="resetZoom">↺</button>
            `;
            visualizationArea.appendChild(controls);

            // 为每个成员创建卡片
            data.forEach(person => {
                const card = document.createElement('div');
                card.className = `person-card ${person.gender === '男' ? 'male' : 'female'}`;
                card.dataset.id = person.id;

                // 尝试加载照片，如果没有则使用占位符
                const imgSrc = `photos/${person.id}.jpg`;
                const img = new Image();
                img.onerror = function() {
                    card.innerHTML = `
                        <div class="person-img" style="background: #e4efe9; display: flex; align-items: center; justify-content: center;">
                            <span style="font-size: 1.5rem;">👤</span>
                        </div>
                        <div class="person-name">${person.name}</div>
                        <div class="person-details">
                            <div>${person.gender}</div>
                            <div>${person.birthdate}</div>
                            <div>${person.birthplace}</div>
                        </div>
                    `;
                    visualizationArea.appendChild(card);
                };

                img.onload = function() {
                    card.innerHTML = `
                        <img class="person-img" src="${imgSrc}" alt="${person.name}">
                        <div class="person-name">${person.name}</div>
                        <div class="person-details">
                            <div>${person.gender}</div>
                            <div>${person.birthdate}</div>
                            <div>${person.birthplace}</div>
                        </div>
                    `;
                    visualizationArea.appendChild(card);
                };

                img.src = imgSrc;
            });

            // 布局家谱树（简化实现）
            layoutTree(data);

            // 重新绑定控制按钮事件
            document.getElementById('zoomIn').addEventListener('click', zoomIn);
            document.getElementById('zoomOut').addEventListener('click', zoomOut);
            document.getElementById('resetZoom').addEventListener('click', resetZoom);

            // 添加卡片点击事件
            document.querySelectorAll('.person-card').forEach(card => {
                card.addEventListener('click', () => {
                    document.querySelectorAll('.person-card').forEach(c => c.classList.remove('highlight'));
                    card.classList.add('highlight');
                });
            });
        }

        // 布局家谱树（简化实现）
        function layoutTree(data) {
            const cards = document.querySelectorAll('.person-card');
            const centerX = document.getElementById('visualizationArea').offsetWidth / 2;

            // 简单按世代布局
            const byGeneration = {};
            data.forEach(person => {
                // 简化计算世代：没有父母的是第一代
                let generation = 1;
                if (person.father || person.mother) {
                    generation = 2;
                }

                const children = data.filter(p => p.father == person.id || p.mother == person.id);
                if (children.length > 0) {
                    generation = Math.min(generation, 3); // 简化处理
                }

                if (!byGeneration[generation]) byGeneration[generation] = [];
                byGeneration[generation].push(person);
            });

            // 设置每个卡片的位置
            Object.keys(byGeneration).forEach(generation => {
                const members = byGeneration[generation];
                const yPos = 50 + (generation - 1) * 180;

                members.forEach((person, index) => {
                    const card = document.querySelector(`.person-card[data-id="${person.id}"]`);
                    if (card) {
                        const xPos = centerX - (members.length * 180) / 2 + index * 200;
                        card.style.left = `${xPos}px`;
                        card.style.top = `${yPos}px`;
                    }
                });
            });

            // 实际应用中需要更复杂的布局算法来绘制连接线
        }

        // 筛选家谱树
        function filterTree() {
            const searchText = document.getElementById('searchInput').value.toLowerCase();
            const generation = document.getElementById('generationFilter').value;

            document.querySelectorAll('.person-card').forEach(card => {
                const name = card.querySelector('.person-name').textContent.toLowerCase();
                const shouldShow =
                    (searchText === '' || name.includes(searchText)) &&
                    (generation === '' || Math.floor(Math.random() * 4) + 1 == generation); // 简化实现

                card.style.display = shouldShow ? 'block' : 'none';
            });
        }

        // 重置视图
        function resetView() {
            document.getElementById('searchInput').value = '';
            document.getElementById('generationFilter').value = '';
            document.querySelectorAll('.person-card').forEach(card => {
                card.style.display = 'block';
                card.classList.remove('highlight');
            });
        }

        // 缩放功能
        let currentScale = 1;

        function zoomIn() {
            currentScale += 0.1;
            applyScale();
        }

        function zoomOut() {
            currentScale -= 0.1;
            applyScale();
        }

        function resetZoom() {
            currentScale = 1;
            applyScale();
        }

        function applyScale() {
            const area = document.getElementById('visualizationArea');
            area.style.transform = `scale(${currentScale})`;
        }

        // 初始化应用
        window.addEventListener('DOMContentLoaded', init);
    </script>
</body>

</html>